Skip to content

Rename "packages" to "integrations" in aspire.config.json with backward compatibility#15633

Open
Copilot wants to merge 3 commits intomainfrom
copilot/rename-packages-to-integrations
Open

Rename "packages" to "integrations" in aspire.config.json with backward compatibility#15633
Copilot wants to merge 3 commits intomainfrom
copilot/rename-packages-to-integrations

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 26, 2026

Description

Renames the "packages" JSON key to "integrations" in aspire.config.json while maintaining full backward compatibility. The system reads both "packages" (legacy) and "integrations" (new) keys, but always writes "integrations" in new or saved files.

Changes

  • AspireConfigFile.cs: Changed [JsonPropertyName("packages")][JsonPropertyName("integrations")] on the Packages property. Added a LegacyPackages property with [JsonPropertyName("packages")] for backward-compatible reading, with MergeLegacyPackages() to merge legacy entries into Packages after deserialization. When both keys exist, "integrations" takes precedence. LegacyPackages is nulled after merge and excluded from serialization via WhenWritingNull.
  • extension/src/utils/cliTypes.ts: Added integrations? to AspireConfigFile interface; kept packages? with @deprecated marker for backward compatibility.
  • extension/schemas/aspire-config.schema.json: Added "integrations" property and kept "packages" as deprecated for backward compatibility.
  • 149 playground aspire.config.json files: Updated key from "packages" to "integrations".
  • Tests: Updated ProjectReferenceTests.cs and ConfigMigrationTests.cs to use "integrations". Added 5 new backward-compatibility tests in AspireConfigFileTests.cs covering: reading legacy "packages" key, reading new "integrations" key, merging both keys, precedence when both exist, and verifying only "integrations" is written on save.

Before / After:

// Before (still readable for backward compat)
{
  "packages": { "Aspire.Hosting.Redis": "9.2.0" }
}

// After (always written in new files)
{
  "integrations": { "Aspire.Hosting.Redis": "9.2.0" }
}

Note: The legacy .aspire/settings.json format (AspireJsonConfiguration) retains its "packages" key unchanged — that format is migrated into aspire.config.json on first use.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Agent-Logs-Url: https://github.com/microsoft/aspire/sessions/991be4bf-31eb-490c-8c07-a1cebce5a01a

Co-authored-by: maddymontaquila <12660687+maddymontaquila@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix rename packages to integrations in aspire.config.json Rename "packages" to "integrations" in aspire.config.json Mar 26, 2026
Copilot AI requested a review from maddymontaquila March 26, 2026 23:56
@davidfowl
Copy link
Copy Markdown
Contributor

@copilot This needs to be backwards compatible. We need to support both now for reading (both packages and integrations) but write integrations in anything new.

… write only integrations

Agent-Logs-Url: https://github.com/microsoft/aspire/sessions/1581ecd1-3d79-4a46-bdd8-030eea387877

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 27, 2026

@copilot This needs to be backwards compatible. We need to support both now for reading (both packages and integrations) but write integrations in anything new.

Added backward compatibility in a25121c. Now:

  • Reading: Both "packages" (legacy) and "integrations" (new) keys are supported. A LegacyPackages property reads "packages", and MergeLegacyPackages() merges entries into Packages after deserialization. When both exist, "integrations" takes precedence.
  • Writing: Always writes "integrations"LegacyPackages is nulled after merge and excluded via WhenWritingNull.
  • JSON schema and TypeScript interface both accept either key.
  • 5 new tests cover: reading legacy key, reading new key, merging both, precedence, and verifying only "integrations" is written.

Copilot AI changed the title Rename "packages" to "integrations" in aspire.config.json Rename "packages" to "integrations" in aspire.config.json with backward compatibility Mar 27, 2026
Copilot AI requested a review from davidfowl March 27, 2026 04:13
@maddymontaquila maddymontaquila requested review from JamesNK and Copilot and removed request for davidfowl and maddymontaquila March 27, 2026 23:21
@maddymontaquila maddymontaquila marked this pull request as ready for review March 27, 2026 23:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates aspire.config.json from the legacy "packages" key to the new "integrations" key while preserving backward-compatible reads, and updates the VS Code extension types/schema plus the playground fixtures accordingly.

Changes:

  • Updated AspireConfigFile JSON serialization to write "integrations" and added a legacy "packages" read path merged post-deserialization.
  • Updated CLI/extension types and JSON schema to recognize "integrations" (keeping "packages" for backward compat).
  • Updated tests and playground aspire.config.json files to use "integrations".

Reviewed changes

Copilot reviewed 155 out of 155 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Aspire.Cli/Configuration/AspireConfigFile.cs Writes "integrations" via [JsonPropertyName], reads legacy "packages" into LegacyPackages and merges on load/save.
tests/Aspire.Cli.Tests/Configuration/AspireConfigFileTests.cs Adds unit tests covering legacy read, new key read, merge behavior, precedence, and save output key.
tests/Aspire.Cli.EndToEnd.Tests/ProjectReferenceTests.cs Updates E2E test mutation logic to write integrations in the config JSON.
tests/Aspire.Cli.EndToEnd.Tests/ConfigMigrationTests.cs Updates E2E CLI command usage from packages to integrations.
extension/src/utils/cliTypes.ts Extends AspireConfigFile TS type with integrations? and keeps packages? as deprecated.
extension/schemas/aspire-config.schema.json Adds "integrations" schema property and retains "packages" with deprecated wording.
playground/**/aspire.config.json Renames "packages""integrations" across the playground configs.
Comments suppressed due to low confidence (1)

extension/schemas/aspire-config.schema.json:207

  • The schema describes packages as deprecated, but VS Code’s JSON schema support won’t typically surface that as a deprecation warning based on the description alone. If the intent is to guide users away from packages, consider adding a VS Code-recognized deprecation marker (e.g., deprecationMessage) to the packages property while keeping it in the schema for backward compatibility.
    "packages": {
      "description": "Deprecated: use \"integrations\" instead. Legacy key for integration references, kept for backward compatibility.",
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },

Comment on lines +112 to +120
/// <summary>
/// Legacy property for backward compatibility. Reads the <c>"packages"</c> key from
/// older aspire.config.json files. Merged into <see cref="Packages"/> after deserialization
/// via <see cref="MergeLegacyPackages"/> (which sets this to <c>null</c>).
/// Never written back because <c>DefaultIgnoreCondition = WhenWritingNull</c> is configured
/// on the serializer context.
/// </summary>
[JsonPropertyName("packages")]
public Dictionary<string, string>? LegacyPackages { get; set; }
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LegacyPackages is intended as a legacy/back-compat input only, but it currently has no [Description]. SettingsSchemaBuilder.BuildConfigFileSchema reflects public properties and uses [Description] for schema/help text, so packages will show up with an empty description in aspire config info --json (and any tooling using that schema). Consider adding a description that explicitly marks it as deprecated/legacy and points users to integrations.

Copilot uses AI. Check for mistakes.
Comment on lines +133 to +136
if (Packages is null)
{
Packages = LegacyPackages;
}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MergeLegacyPackages can’t distinguish between "integrations" being absent vs explicitly set to null in JSON (both deserialize to Packages == null). With the current logic, a file containing "integrations": null and legacy "packages": { ... } will end up using the legacy entries, which contradicts the stated precedence of the new key when both are present. If strict precedence is required, consider deserializing via JsonDocument/JsonNode (or a custom converter) so you can detect whether integrations was present and treat explicit null as an override (i.e., do not merge legacy).

Copilot uses AI. Check for mistakes.
Comment on lines +121 to +123
var packages = config["integrations"] as JsonObject ?? new JsonObject();
packages["MyIntegration"] = "./MyIntegration/MyIntegration.csproj";
config["packages"] = packages;
config["integrations"] = packages;
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local variable is still named packages but it now reads/writes the integrations JSON property. Renaming the variable to integrations (and updating subsequent uses) would avoid confusion when maintaining this test.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants